// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


// A FileHandle is a File pointer plus some (optional, file-type-dependent)
// extra information for speeding up loading columnar data. For example, when
// we open a file we might build a hash map saying what region(s) on disk
// correspond to a given column in a given stripe.
//
// The FileHandle will normally be used in conjunction with a CachedFactory
// to speed up queries that hit the same files repeatedly; see the
// FileHandleCache and FileHandleFactory.

#pragma once

#include <pollux/common/caching/cached_factory.h>
#include <pollux/common/caching/file_ids.h>
#include <pollux/common/config/config.h>
#include <pollux/common/file/file.h>
#include <pollux/connectors/hive/file_properties.h>

namespace kumo::pollux {

// See the file comment.
struct FileHandle {
  std::shared_ptr<ReadFile> file;

  // Each time we make a new FileHandle we assign it a uuid and use that id as
  // the identifier in downstream data caching structures. This saves a lot of
  // memory compared to using the filename as the identifier.
  StringIdLease uuid;

  // Id for the group of files this belongs to, e.g. its
  // directory. Used for coarse granularity access tracking, for
  // example to decide placing on SSD.
  StringIdLease groupId;

  // We'll want to have a hash map here to record the identifier->byte range
  // mappings. Different formats may have different identifiers, so we may need
  // a union of maps. For example in orc you need 3 integers (I think, to be
  // confirmed with xldb): the row bundle, the node, and the sequence. For the
  // first diff we'll not include the map.
};

/// Estimates the memory usage of a FileHandle object.
struct FileHandleSizer {
  uint64_t operator()(const FileHandle& a);
};

using FileHandleCache = SimpleLRUCache<std::string, FileHandle>;

// Creates FileHandles via the Generator interface the CachedFactory requires.
class FileHandleGenerator {
 public:
  FileHandleGenerator() {}
  FileHandleGenerator(std::shared_ptr<const config::ConfigBase> properties)
      : properties_(std::move(properties)) {}
  std::unique_ptr<FileHandle> operator()(
      const std::string& filename,
      const FileProperties* properties,
      filesystems::File::IoStats* stats);

 private:
  const std::shared_ptr<const config::ConfigBase> properties_;
};

using FileHandleFactory = CachedFactory<
    std::string,
    FileHandle,
    FileHandleGenerator,
    FileProperties,
    filesystems::File::IoStats,
    FileHandleSizer>;

using FileHandleCachedPtr = CachedPtr<std::string, FileHandle>;

using FileHandleCacheStats = SimpleLRUCacheStats;

} // namespace kumo::pollux
